/**
 * @file /include/ecl/threads/thread_exceptions_pos.hpp
 *
 * @brief Exception handlers for pthreads.
 *
 * @date Jun 30, 2009
 **/
/*****************************************************************************
** Ifdefs
*****************************************************************************/

#ifndef ECL_THREADS_THREAD_EXCEPTIONS_POS_HPP_
#define ECL_THREADS_THREAD_EXCEPTIONS_POS_HPP_

/*****************************************************************************
** Platform Check
*****************************************************************************/

#include <ecl/config/ecl.hpp>
#if defined(ECL_IS_POSIX)

/*****************************************************************************
** Includes
*****************************************************************************/

#include <string>
#include <errno.h>
#include <ecl/errors/handlers.hpp>

/*****************************************************************************
** Namespaces
*****************************************************************************/

namespace ecl {
namespace threads {

/*****************************************************************************
** Interface [Errors]
*****************************************************************************/
/**
 * This function generates the required ecl Error response
 * for posix error numbers generated by <i>pthread_create</i> calls.
 *
 * @param error_result : thread functions do not use errno, so we must pass this function result directly to the handler.
 * @return Error : the appropriate standardised ecl Error response.
 */
inline Error ECL_LOCAL handlePthreadCreateError(int error_result) {
	switch (error_result) {
		case ( EINVAL ) : return Error(InvalidInputError);
		case ( EAGAIN ) : return Error(MemoryError);
		case ( EPERM )  : return Error(PermissionsError);
		default         : return Error(UnknownError);
	}
}
} // namespace threads
} // namespace ecl

/*****************************************************************************
** Interface [Exceptions]
*****************************************************************************/

#include <ecl/exceptions/macros.hpp>
#if defined(ECL_HAS_EXCEPTIONS)

/*****************************************************************************
** Includes
*****************************************************************************/

#include <string>
#include <ecl/exceptions/standard_exception.hpp>

/*****************************************************************************
** Namespaces
*****************************************************************************/

namespace ecl {
namespace threads {

/*****************************************************************************
** Functions
*****************************************************************************/
/**
 * This function generates a custom StandardException response
 * for posix error numbers generated by <i>pthread_create</i> calls.
 * @param loc : use with the LOC macro, identifies the line and file of the code.
 * @param error_result : thread functions do not use errno, so we must pass this function result directly to the handler.
 * @return StandardException : the appropriate ecl standardised exception.
 */
inline StandardException ECL_LOCAL throwPthreadCreateException(const char* loc, int error_result) {
	switch (error_result) {
		case ( EINVAL ) : return StandardException(loc, InvalidInputError, "Invalid settings in 'attr'");
		case ( EAGAIN ) : return StandardException(loc, MemoryError, "Insufficient resources to create another thread.");
		case ( EPERM )  : return StandardException(loc, PermissionsError, "No permission to set the scheduling policy and parameters specified in attr.");
		default         : return StandardException(loc, UnknownError, "Unknown error.");
	}
}

/**
 * This function generates a custom StandardException response
 * for posix error numbers generated by <i>pthread_create</i> calls.
 * @param loc : use with the LOC macro, identifies the line and file of the code.
 * @param error_result : thread functions do not use errno, so we must pass this function result directly to the handler.
 */
inline StandardException ECL_LOCAL throwPthreadJoinException(const char* loc, int error_result) {
	switch (error_result) {
		case ( EDEADLK ) : return StandardException(loc, UsageError, "Deadlock! Two threads tried to join each other or a thread tried to join itself.");
		case ( EINVAL )  : return StandardException(loc, InvalidInputError, "The specified thread is not joinable or another thread is already waiting to join with it.");
		case ( ESRCH )   : return StandardException(loc, InvalidInputError, "The specified thread (id) could not be found. Probably its already been joined?");
		default          : return StandardException(loc, UnknownError, "Unknown error.");
	}
}
/**
 * This function generates a custom StandardException response
 * for posix error numbers generated by <i>pthread_cancel</i> calls.
 * @param loc : use with the LOC macro, identifies the line and file of the code.
 * @param error_result : thread functions do not use errno, so we must pass this function result directly to the handler.
 */
inline StandardException ECL_LOCAL throwPthreadCancelException(const char* loc, int error_result) {
	switch (error_result) {
		case ( ESRCH )   : return StandardException(loc, InvalidInputError, "The specified thread (id) could not be found. Probably its already terminated.");
		default          : return StandardException(loc, UnknownError, "Unknown error.");
	}
}

} // namespace threads
} // namespace ecl

#endif /* ECL_HAS_EXCEPTIONS */
#endif /* ECL_IS_POSIX */
#endif /* ECL_THREADS_THREAD_EXCEPTIONS_POS_HPP_ */
